package com.juc.threadlocal;

import java.lang.ref.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author : Zan
 * @Create : 2024/5/12 14:34
 * @ClassName : ReferenceDemo
 * @Description : TODO 请用一句话描述该类的功能
 */

class MyObject {

    // 这个方法一般不用复写，只是为了教学给大家进行案例演示做说明
    @Override
    protected void finalize() throws Throwable {
        // finalize的通常目的是在对象被不可撤销地丢弃之前执行清理操作
        System.out.println("---- invoke finalize method ... ! ! !");
    }
}

public class ReferenceDemo {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        // 引用队列
        ReferenceQueue<MyObject> referenceQueue = new ReferenceQueue<>();
        PhantomReference<MyObject> phantomReference = new PhantomReference<>(myObject, referenceQueue);

        // null
//        System.out.println(phantomReference.get());

        List<byte[]> list = new ArrayList<>();

        new Thread(() -> {
            while (true) {
                list.add(new byte[1 * 1024 * 1024]); // 1MB
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(phantomReference.get() + "\t list add ok");
            }
        }, "t1").start();

        new Thread(() -> {
            while (true) {
                // 取出这个队列的值
                Reference<? extends MyObject> reference = referenceQueue.poll();
                if (reference != null) {
                    System.out.println("----- 虚对象被回收，加入了队列 ... ! ! !");
                    break;
                }
            }
        }, "t2").start();
    }

    private static void weakReference() {
        WeakReference<MyObject> weakReference = new WeakReference<>(new MyObject());
        System.out.println("----- gc before 内存够用: " + weakReference.get());

        System.gc();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("----- gc after 内存够用: " + weakReference.get());
    }

    private static void softReference() {
        // -Xms10m -Xmx10m
        SoftReference<MyObject> softReference = new SoftReference<>(new MyObject());

        System.out.println("-----softReference: " + softReference.get());

        System.gc();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("-----gc after 内存够用 - softReference: " + softReference.get());

        try {
            byte[] bytes = new byte[20 * 1024 * 1024];// 20MB对象
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("-----gc after 内存不够 - softReference: " + softReference.get());
        }
    }

    private static void strongReference() {
        MyObject myObject = new MyObject();
        System.out.println("gc before: " + myObject);

        myObject = null;

        System.gc(); // 人工开启垃圾回收GC，一般不用

        try {
            TimeUnit.MILLISECONDS.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("gc after: " + myObject);
    }
}
